// joy_buildcheck.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <common/guard/modcheck.h>
#include <common/guard/strcrypt.h>
#include <common/guard/apihelp.h>

#ifdef _DEBUG
#   pragma comment(lib, "joy_guard_d.lib")
#else
#   pragma comment(lib, "joy_guard.lib")
#endif
void insert_i(std::vector<BYTE>& buf, DWORD i)
{
    buf.insert(buf.end(), (BYTE*)&i, (BYTE*)(&i+1));
}

int _tmain(int argc, _TCHAR* argv[])
{
    if(argc != 3)
    {
        printf("bad command line parameters.\n");
        return 0;
    }

    JoyGuard::ModCheck::ModData modData;

    if(strcmp(argv[1], "-f") == 0)
    {
        if(!JoyGuard::ModCheck::BuildModDataFromFile(argv[2], modData))
        {
            printf("build check failed.\n");
            return 0;
        }
    }
    else if(strncmp(argv[1], "-p", 2) == 0)
    {
        DWORD processId = atoi(argv[1]+2);
        HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
        if(process == NULL)
        {
            printf("failed open process.\n");
            return 0;
        }
        HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
        BYTE* modBase = NULL;
        MODULEENTRY32 me32;
        hModuleSnap = JoyGuard::ApiHelp::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId);
        if(hModuleSnap != INVALID_HANDLE_VALUE)
        {
            me32.dwSize = sizeof( MODULEENTRY32 );

            if(JoyGuard::ApiHelp::Module32First(hModuleSnap, &me32))
            {
                do
                {
                    if(stricmp(me32.szModule, argv[2]) == 0)
                    {
                        modBase = me32.modBaseAddr;
                    }
                }
                while(JoyGuard::ApiHelp::Module32Next(hModuleSnap, &me32));
            }

            ::CloseHandle(hModuleSnap);
        }
        if(modBase == NULL)
        {
            printf("cannot find module %s.\n", argv[2]);
            return 0;
        }
        JoyGuard::ModCheck::BuildModDataFromModule(process, modBase, modData);
    }
    else if(strncmp(argv[1], "-l", 2) == 0)
    {
        HMODULE hMod = ::LoadLibrary(argv[2]);
        if(hMod == NULL)
        {
            printf("cannot load module %s.\n", argv[2]);
            return 0;
        }
        JoyGuard::ModCheck::BuildModDataFromModule(GetCurrentProcess(), (BYTE*)hMod, modData);
        ::FreeLibrary(hMod);
    }
    else
    {
        printf("bad command line option.\n");
        return 0;
    }

    char* p = argv[2]+strlen(argv[2]);
    for( ; p > argv[2]; -- p)
    {
         if(*p == '/' || *p == '\\')
         {
             -- p;
             break;
         }
         if(*p == '.')
         {
             *p = '_';
         }
    }

    std::vector<BYTE> buf;
    insert_i(buf, modData.m_headerHash);
    insert_i(buf, (DWORD)modData.m_headerData.size());
    buf.insert(buf.end(), modData.m_headerData.begin(), modData.m_headerData.end());
    insert_i(buf, (DWORD)modData.m_codeDatas.size());
    buf.insert(buf.end(),
        (BYTE*)&*modData.m_codeDatas.begin(),
        (BYTE*)&*modData.m_codeDatas.end());

    JoyGuard::StrCrypt::EncryptData(&buf[0], &buf[0], buf.size());
    
    FILE* f = fopen("check.h", "w");

    fprintf(f, "BYTE mod_check_%s[] = \n{", p);

    for(int i = 0; i < (int)buf.size(); ++ i)
    {
        if(i % 16 == 0)
        {
            fprintf(f, "\n    ");
        }
        fprintf(f, "0x%.2x,", buf[i]);
    }

    fprintf(f, "\n};\n");

    fclose(f);
    return 0;
}

